import { Coupon, CouponType } from "@mallfoundry/marketing/coupon"
import { Button, Col, DatePicker, Divider, Form, Input, InputNumber, Radio, Row, Space, Typography } from "antd"
import * as dayjs from "dayjs"
import * as _ from "lodash"
import { RuleObject } from "rc-field-form/lib/interface"
import * as React from "react"
import { useEffect, useState } from "react"
import classes from "./coupon-form.module.scss"
import CouponPreview from "./coupon-preview"

const { Title } = Typography

const DATE_TIME_FORMAT = "YYYY-MM-DD HH:mm:ss"

interface FormLegendProps {
  name: string
}

function FormLegend(props: FormLegendProps) {
  const { name } = props
  return <>
    <Title level={5}>{name}</Title>
    <Divider plain style={{ marginTop: "0" }}/>
  </>
}

enum UseThreshold {
  NoThreshold,
  AmountThreshold,
}

class CouponFormValue extends Coupon {
  public useThreshold: UseThreshold = UseThreshold.NoThreshold
}

const layout = {
  labelCol: { span: 4 },
  wrapperCol: { span: 8 },
}
const dateLayout = {
  labelCol: { span: 4 },
  wrapperCol: { span: 12 },
}
const tailLayout = {
  wrapperCol: { offset: 4, span: 8 },
}

function normalizeFields(values: any) {
  const { startTime, endTime, useThreshold, minAmount = 0, ...source } = values
  return {
    ...source,
    minAmount: useThreshold === UseThreshold.AmountThreshold ? minAmount : undefined,
    startTime: _.isEmpty(startTime) ? undefined : startTime.format(DATE_TIME_FORMAT),
    endTime: _.isEmpty(endTime) ? undefined : endTime.format(DATE_TIME_FORMAT),
  }
}

interface CouponFormProps {
  loading: boolean
  coupon: Coupon
  onFinish: (coupon: Coupon) => void
  onCancel: () => void
}

export default function CouponForm(props: CouponFormProps) {
  const { coupon, loading, onFinish, onCancel } = props
  const { type } = coupon
  const [form] = Form.useForm<CouponFormValue>()
  const [couponPreview, setCouponPreview] = useState(new Coupon())
  const [couponFormValue, setCouponFormValue] = useState(new CouponFormValue())
  const [useThreshold, setUseThreshold] = useState(UseThreshold.NoThreshold)
  const [autoDescription, setAutoDescription] = useState(true)

  useEffect(() => {
    const newUseThreshold = _.isEmpty(coupon.minAmount) && !_.isNumber(coupon.minAmount) ? UseThreshold.NoThreshold : UseThreshold.AmountThreshold
    setUseThreshold(newUseThreshold)
    setCouponFormValue(_.assign(new CouponFormValue(), coupon, {
      useThreshold: newUseThreshold,
    }))
    setCouponPreview(coupon)
  }, [coupon])

  useEffect(() => {
    setUseThreshold(couponFormValue.useThreshold)
    const { startTime = "", endTime = "", ...formValue } = couponFormValue
    form.setFieldsValue({
      ...formValue,
      // @ts-ignore
      startTime: _.isEmpty(startTime) ? undefined : dayjs(startTime),
      // @ts-ignore
      endTime: _.isEmpty(endTime) ? undefined : dayjs(endTime),
    })
  }, [form, couponFormValue])

  function minAmountValidator(rule: RuleObject, value: any) {
    if (useThreshold === UseThreshold.AmountThreshold) {
      const discountAmount = form.getFieldValue("discountAmount")
      if (_.isUndefined(value) || value <= 0) {
        return Promise.reject("请输入订单满足金额")
      } else if (useThreshold === UseThreshold.AmountThreshold && discountAmount > value) {
        return Promise.reject("使用门槛金额不能低于优惠减免金额")
      }
    }
    return Promise.resolve()
  }

  function discountAmountValidator(rule: RuleObject, value: any) {
    const minAmount = form.getFieldValue("minAmount")
    if (_.isUndefined(value) || value <= 0) {
      return Promise.reject("请输入优惠金额")
    } else if (useThreshold === UseThreshold.AmountThreshold && value > minAmount) {
      return Promise.reject("优惠减免金额必须小于等于优惠券使用门槛金额")
    }
    return Promise.resolve()
  }

  function issuingCountValidator(rule: RuleObject, value: any) {
    if (_.isUndefined(value)) {
      return Promise.reject("请输入发放总量")
    } else if (value <= 0) {
      return Promise.reject("发放总量不能小于0")
    }
    return Promise.resolve()
  }

  function discountMaxAmountValidator(rule: RuleObject, value: any) {
    const discountMinAmount = form.getFieldValue("discountMinAmount")
    if (_.isUndefined(value)) {
      return Promise.reject("请输入上限优惠金额")
    } else if (discountMinAmount >= value) {
      return Promise.reject("随机优惠金额范围的上限必须大于下限")
    }
    return Promise.resolve()
  }

  function onSubmit() {
    form.validateFields().then(values => _.assign(new Coupon(), normalizeFields(values)))
      .then(onFinish)
  }

  function onValuesChange(changedValues: CouponFormValue, allValues: CouponFormValue) {
    if (!_.isUndefined(changedValues.useThreshold) && changedValues.useThreshold !== useThreshold) {
      setUseThreshold(changedValues.useThreshold)
    }
    if (_.has(changedValues, "description") && autoDescription) {
      setAutoDescription(false)
    }
    if (!_.has(changedValues, "description") && autoDescription) {
      const description = []

      description.push("优惠内容：全部商品可用")
      if (allValues.useThreshold === UseThreshold.NoThreshold) {
        description.push("，满任意金额可用")
      } else if (allValues.minAmount > 0) {
        description.push(`，满${allValues.minAmount}元可用`)
      }
      form.setFieldsValue({ description: description.join("") })
    }
    setCouponPreview(_.assign(new Coupon(), couponPreview, normalizeFields(form.getFieldsValue())))
  }

  return (
    <>
      <Row gutter={[16, 16]}>
        <Col span={6}>
          <CouponPreview coupon={couponPreview}/>
        </Col>
        <Col span={12}>
          <div className={classes.CouponForm}>
            <Form {...layout} form={form} onValuesChange={onValuesChange}>
              <FormLegend name="基本信息"/>
              <Form.Item name="id" hidden><Input/></Form.Item>
              <Form.Item name="storeId" hidden><Input/></Form.Item>
              <Form.Item name="type" hidden><Input/></Form.Item>
              <Form.Item label="优惠券名称" name="name" rules={[{ required: true, message: "请输入优惠券名称" }]}>
                <Input/>
              </Form.Item>
              <Form.Item label="发放总量" required>
                <Form.Item name="issuingCount" noStyle
                           rules={[{ validator: issuingCountValidator }]}>
                  <InputNumber min={1} max={100000000} placeholder="最多100000000张" style={{ width: "160px" }}/>
                </Form.Item>
                <span className="ant-form-text">张</span>
              </Form.Item>
              <Form.Item label="使用门槛" name="useThreshold" required>
                <Radio.Group>
                  <Radio className={classes.NoMinAmount} value={UseThreshold.NoThreshold}>无使用门槛</Radio>
                  <Radio value={UseThreshold.AmountThreshold}>
                    <span className="ant-form-text">订单满</span>
                    <Form.Item name="minAmount" noStyle
                               dependencies={["discountAmount"]}
                               rules={[{ validator: minAmountValidator }]}>
                      <InputNumber min={0.01} max={100000000} precision={2}
                                   disabled={useThreshold === UseThreshold.NoThreshold}/>
                    </Form.Item>
                    <span className="ant-form-text">元</span>
                  </Radio>
                </Radio.Group>
              </Form.Item>
              {
                type === CouponType.FixedDiscount &&
                <Form.Item label="优惠内容" required  {...dateLayout}>
                  <span className="ant-form-text">减免</span>
                  <Form.Item name="discountAmount" noStyle
                             dependencies={["minAmount"]}
                             rules={[{ validator: discountAmountValidator }]}>
                    <InputNumber min={0.01} max={100000} precision={2}/>
                  </Form.Item>
                  <span className="ant-form-text">元</span>
                </Form.Item>
              }
              {
                type === CouponType.PercentageDiscount &&
                <Form.Item label="优惠内容" required  {...dateLayout}>
                  <span className="ant-form-text">打</span>
                  <Form.Item name="discountPercent" noStyle rules={[{ required: true, message: "请输入优惠折扣" }]}>
                    <InputNumber min={0.1} max={9.9}/>
                  </Form.Item>
                  <span className="ant-form-text">折</span>
                </Form.Item>
              }
              {
                type === CouponType.RandomDiscount &&
                <Form.Item label="优惠内容" required  {...dateLayout}>
                  <span className="ant-form-text">随机范围</span>
                  <Form.Item name="discountMinAmount" noStyle rules={[{ required: true, message: "请输入下限优惠金额" }]}>
                    <InputNumber min={0.01} max={10000}/>
                  </Form.Item>
                  <span className="ant-form-text">至</span>
                  <Form.Item name="discountMaxAmount" noStyle
                             dependencies={["discountMinAmount"]}
                             rules={[{ validator: discountMaxAmountValidator }]}>
                    <InputNumber min={0.01} max={10000}/>
                  </Form.Item>
                  <span className="ant-form-text">元</span>
                </Form.Item>
              }
              <Form.Item label="用券时间" required {...dateLayout}>
                <Form.Item name="startTime" style={{ display: "inline-block", width: "calc(50% - 12px)", marginBottom: 0 }}>
                  <DatePicker showTime format={DATE_TIME_FORMAT} placeholder="开始日期" style={{ width: "100%" }}/>
                </Form.Item>
                <span style={{ display: "inline-block", width: "24px", lineHeight: "32px", textAlign: "center" }}>至</span>
                <Form.Item name="endTime" style={{ display: "inline-block", width: "calc(50% - 12px)", marginBottom: 0 }}>
                  <DatePicker showTime format={DATE_TIME_FORMAT} placeholder="结束日期" style={{ width: "100%" }}/>
                </Form.Item>
              </Form.Item>
              <Form.Item label="使用说明" name="description"  {...dateLayout}>
                <Input.TextArea placeholder="建议填写优惠券的具体使用信息"
                                autoSize={{ minRows: 4, maxRows: 6 }}/>
              </Form.Item>
              <Form.Item {...tailLayout} style={{ marginBottom: 0 }}>
                <Space>
                  <Button type="primary" loading={loading} onClick={onSubmit}>保存</Button>
                  <Button onClick={onCancel}>取消</Button>
                </Space>
              </Form.Item>
            </Form>
          </div>
        </Col>
      </Row>
    </>
  )
}
